package com.lion.common.spring.enhancers.helpers;

import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 简化的泛型解析器（只需要Class类型时）
 */
public class SimpleGenericResolver {

    /**
     * 解析方法参数的实际Class类型
     */
    public static Class<?> resolveParameterClass(MethodParameter parameter, Class<?> targetTypeClass) {
        // 添加判断：只有需要处理的情况才进行泛型解析
        if (!shouldProcessGenericResolution(parameter, targetTypeClass)) {
            return parameter.getParameterType();
        }

        // 查找接口泛型映射
        Class<?> interfaceClass = Objects.requireNonNull(parameter.getMethod()).getDeclaringClass();
        Map<String, Class<?>> genericMapping = getGenericClassMapping(targetTypeClass, interfaceClass);

        // 如果是泛型参数，返回映射的具体Class
        if (parameter.getGenericParameterType() instanceof TypeVariable) {
            TypeVariable<?> tv = (TypeVariable<?>) parameter.getGenericParameterType();
            return genericMapping.getOrDefault(tv.getName(), parameter.getParameterType());
        }

        return parameter.getParameterType();
    }

    /**
     * 获取泛型名称到具体Class的映射
     */
    private static Map<String, Class<?>> getGenericClassMapping(Class<?> targetTypeClass, Class<?> interfaceClass) {
        Map<String, Class<?>> mapping = new HashMap<>();

        for (Type genericInterface : targetTypeClass.getGenericInterfaces()) {
            if (genericInterface instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType) genericInterface;
                if (pt.getRawType().equals(interfaceClass)) {
                    Type[] typeParams = ((Class<?>) pt.getRawType()).getTypeParameters();
                    Type[] actualArgs = pt.getActualTypeArguments();

                    for (int i = 0; i < typeParams.length; i++) {
                        if (typeParams[i] instanceof TypeVariable && actualArgs[i] instanceof Class) {
                            mapping.put(((TypeVariable<?>) typeParams[i]).getName(), (Class<?>) actualArgs[i]);
                        }
                    }
                    break;
                }
            }
        }

        return mapping;
    }

    /**
     * 判断是否需要处理泛型解析的辅助方法
     * 只有满足以下条件才进行处理：
     * 1. 方法是接口的默认方法
     * 2. 该默认方法在实现类中没有被重写
     * 3. 实现类有@Controller或@RestController注解
     */
    private static boolean shouldProcessGenericResolution(MethodParameter parameter, Class<?> targetTypeClass) {
        Method method = parameter.getMethod();

        // 1. 检查方法是否为接口的默认方法
        if (method == null || !method.isDefault()) {
            return false;
        }

        // 2. 获取实际的实现类（从MethodParameter中获取）
        Class<?> implementationClass = parameter.getContainingClass();

        // 3. 检查实现类是否有@Controller或@RestController注解
        boolean isController = AnnotatedElementUtils.hasAnnotation(implementationClass, Controller.class) ||
                AnnotatedElementUtils.hasAnnotation(implementationClass, RestController.class);
        if (!isController) {
            return false;
        }

        // 4. 检查该方法是否在实现类中被重写
        // 获取接口中声明的方法
        Method interfaceMethod = method;

        // 检查实现类中是否有相同签名的方法（即被重写）
        try {
            Method implementationMethod = implementationClass.getMethod(
                    interfaceMethod.getName(),
                    interfaceMethod.getParameterTypes()
            );

            // 如果实现类中的方法不是默认方法，说明被重写了，不需要处理
            if (!implementationMethod.isDefault()) {
                return false;
            }

            // 如果实现类中的方法声明类不是接口，说明被重写了
            if (!implementationMethod.getDeclaringClass().isInterface()) {
                return false;
            }

        } catch (NoSuchMethodException e) {
            // 实现类中没有对应方法，这不应该发生，但安全起见返回false
            return false;
        }

        // 5. 额外检查：targetTypeClass应该是泛型参数类型（如P、U、R等）
        // 如果不是TypeVariable，说明可能不是我们需要处理的情况
        if (!(parameter.getGenericParameterType() instanceof TypeVariable)) {
            return false;
        }

        // 所有条件都满足，需要处理泛型解析
        return true;
    }
}